#pragma once

#include <memory>
#include "Containers/Containers.h"
#include "Reflection/FunctionID.h"

#include "ScriptCompiler/Description/IdentifierDescription.h"
#include "DecoratedTypeDescription.h"

class CDecoratorDescription;
class CExpressionNode;
class CParameterDescription;
class CFunctionBodyDescription;
class CTypeDescription;

class CFunctionDescription : public IIdentifierDescription
{

public:
    virtual EIdentifierType GetIdentifierType() const override
    {
        return EIdentifierType::Function;
    }

    uint32_t IndexInParent = 0;

    //index in all function array, include constructor and base class functions
    int32_t FunctionIndex = -1;

    //index in virtual table, -1 means not in virtual table
    int32_t PositionInVirtualTable=-1;
    
    SFunctionID GetFunctionID() const;

    TVector<CString> ParentScopeNameChain;
    CString Name;

    std::weak_ptr<CTypeDescription> ParentClass;

    SDecoratedTypeDescription ReturnType;

    TVector<std::shared_ptr<CParameterDescription>> Parameters;

    // might be null for native function  / virtual function / interface function
    TOptional<std::shared_ptr<CFunctionBodyDescription>> Body;

    SDecoratedTypeDescription FunctionPointerType;

    //std::shared_ptr<CExpressionNode> Implement;

    virtual CString GetSearchName() const override
    {
        return Name;
    }

    CString GetFunctionName() const
    {
        return Name;
    }

    bool IsStatic() const;
    void SetStatic(bool bInIsStatic);

    bool IsVirtual() const;
    void SetVirtual(bool bInIsVirtual);

    bool IsOverride() const;
    void SetOverride(bool bInIsOverride);

    bool IsNew() const;
    void SetNew(bool bInIsNew);
protected:
    bool bIsStatic = false;
    bool bIsVirtual=false;
    bool bIsOverride=false;
    bool bIsNew=false; //new decorator, only valid for hide base class function

};